package com.ypan.uninstaller.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import android.app.Activity;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;

import com.ypan.uninstaller.MainApp;
import com.ypan.uninstaller.R;
import com.ypan.uninstaller.adapter.ApkInfo;
import com.ypan.uninstaller.logger.SLog;

/**
 * @ClassName: PackageUtils
 * @Description: 包工具类
 * @author Administrator
 * @date 2012-8-8 上午12:08:15
 */
public class PackageUtils {

	// get apk info from apk path
	public static ApkInfo getApkInfo(String apkPath) {
		ApkInfo apkInfo = null;
		PackageManager pm = MainApp.sInstance.getPackageManager();
		PackageInfo info = pm.getPackageArchiveInfo(apkPath,
				PackageManager.GET_ACTIVITIES);
		if (info != null) {
			apkInfo = new ApkInfo(pm, info, apkPath);
		}
		return apkInfo;
	}

	// install apk
	public static void install(Activity activity, String path) {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setDataAndType(Uri.fromFile(new File(path)),
				"application/vnd.android.package-archive");
		activity.startActivity(intent);
	}

	// uninstall a apk
	public static void uninstall(Activity activity, String pkg) {
		if (pkg == null) {
			return;
		}
		Uri uri = Uri.fromParts("package", pkg, null);
		Intent intent = new Intent(Intent.ACTION_DELETE, uri);
		activity.startActivity(intent);
	}

	// install
	private static void install_root_failed(Activity activity, String path,
			int msgwhat, Handler callback) {
		// 取得root失败
		SharePreferences.setHasRoot(false);
		if (callback != null) {
			Message msg = new Message();
			msg.what = msgwhat;
			msg.obj = 3; // root权限获取失败
			callback.sendMessage(msg);
		}
		SLog.e("test", "install_root_failed");
		install(activity, path);
	}

	public static void install_root(final Activity activity, final String path,
			final int msgwhat, final Handler callback) {
		install(activity, path);
	}

	// root卸载普通应用程序
	private static void uninstall_root_failed(final Activity activity,
			final ApkInfo info, final int msgwhat, final Handler callback) {
		SharePreferences.setHasRoot(false);
		if (callback != null) {
			Message msg = new Message();
			msg.what = msgwhat;
			msg.obj = 3; // root权限获取失败
			callback.sendMessage(msg);
		}
		SLog.e("test", "uninstall_root_failed 取得root失败");
		uninstall(activity, info.packageName);
	}

	public static boolean checkBrowser(PackageManager pm, String packageName) {
		if (packageName == null || "".equals(packageName))
			return false;
		try {
			ApplicationInfo info = pm.getApplicationInfo(packageName,
					PackageManager.GET_UNINSTALLED_PACKAGES);
			return true;
		} catch (NameNotFoundException e) {
			return false;
		}
	}

	public static boolean isRooted(Context context) {
		File sufilebin = new File("/data/data/root");
		try {
			sufilebin.createNewFile();
			if (sufilebin.exists()) {
				sufilebin.delete();
			}
			return true;
		} catch (IOException e) {
			PackageManager pm = context.getPackageManager();
			if (checkBrowser(pm, "com.noshufou.android.su")
					|| checkBrowser(pm, "com.miui.uac")) {
				return true;
			}
			return false;
		}

	}

	public static void uninstall_root_app(final Activity activity,
			final ApkInfo info, final int msgwhat, final Handler callback) {
		uninstall(activity, info.packageName);
	}

	// root卸载系统应用程序
	public static void uninstall_root_sys(final Activity activity,
			final ApkInfo info, final int msgwhat, final Handler callback) {
		//Log.e("test", "uninstall_root_sys = "+info.packageName);
		int result = PkgUtils.uninstall(activity, info.packageName);
		//Log.e("test", "result = "+result);
		if(result == PkgUtils.DELETE_SUCCEEDED){
			return;
		}
		Process process = null;
		OutputStream out = null;
		InputStream in = null;
		try {
			// 请求root
			process = Runtime.getRuntime().exec("su");
			out = process.getOutputStream();
			// 直接删除系统的应用程序
			out.write(("mount -o remount rw /system" + "\n" + "rm "
					+ info.dataDir + "\n").getBytes());
			//Log.e("test", "cmd = "
			//		+ ("mount -o remount rw /system" + "\n" + "rm "
			//				+ info.dataDir + "\n"));
			//Log.e("test", "1****1");

		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (out != null) {
					out.flush();
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			//Log.e("test", "2*****2");
		}
	}

	// share apk
	public static void share(Activity activity, String file) {
		if (file == null) {
			return;
		}
		Intent intent = new Intent(Intent.ACTION_SEND);
		intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(file)));
		intent.setType("text/plain");
		String title = MainApp.sInstance.getResources().getString(
				R.string.share);
		activity.startActivity(Intent.createChooser(intent, title));
	}

	// start app
	public static void startAPP(Activity activity, String appPackageName) {
		if (TextUtils.isEmpty(appPackageName)) {
			return;
		}
		PackageManager pm = MainApp.sInstance.getPackageManager();
		Intent startIntent = pm.getLaunchIntentForPackage(appPackageName);
		activity.startActivity(startIntent);
	}

	// start app detail
	private static final String SCHEME = "package";
	/**
	 * 调用系统InstalledAppDetails界面所需的Extra名称(用于Android 2.1及之前版本)
	 */
	private static final String APP_PKG_NAME_21 = "com.android.settings.ApplicationPkgName";
	/**
	 * 调用系统InstalledAppDetails界面所需的Extra名称(用于Android 2.2)
	 */
	private static final String APP_PKG_NAME_22 = "pkg";
	/**
	 * InstalledAppDetails所在包名
	 */
	private static final String APP_DETAILS_PACKAGE_NAME = "com.android.settings";
	/**
	 * InstalledAppDetails类名
	 */
	private static final String APP_DETAILS_CLASS_NAME = "com.android.settings.InstalledAppDetails";

	/**
	 * 调用系统InstalledAppDetails界面显示已安装应用程序的详细信息。 对于Android 2.3（Api Level
	 * 9）以上，使用SDK提供的接口； 2.3以下，使用非公开的接口（查看InstalledAppDetails源码）。
	 * 
	 * @param context
	 * @param packageName
	 *            应用程序的包名
	 */
	public static void showInstalledAppDetails(Activity activity,
			String packageName) {
		Intent intent = new Intent();
		final int apiLevel = Build.VERSION.SDK_INT;
		if (apiLevel >= 9) { // 2.3（ApiLevel 9）以上，使用SDK提供的接口
			intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
			Uri uri = Uri.fromParts(SCHEME, packageName, null);
			intent.setData(uri);
		} else { // 2.3以下，使用非公开的接口（查看InstalledAppDetails源码）
			// 2.2和2.1中，InstalledAppDetails使用的APP_PKG_NAME不同。
			final String appPkgName = (apiLevel == 8 ? APP_PKG_NAME_22
					: APP_PKG_NAME_21);
			intent.setAction(Intent.ACTION_VIEW);
			intent.setClassName(APP_DETAILS_PACKAGE_NAME,
					APP_DETAILS_CLASS_NAME);
			intent.putExtra(appPkgName, packageName);
		}
		activity.startActivity(intent);
	}

	// start app in market
	public static void startAppInMarket(Activity activity, String packageName) {
		StringBuilder sb = new StringBuilder().append("market://details?id=");
		sb.append(packageName);
		Uri localUri = Uri.parse(sb.toString());
		Intent localIntent = new Intent("android.intent.action.VIEW", localUri);
		localIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		activity.startActivity(localIntent);
	}

	// search apk
	public static void searchApp(Activity activity, String apk) {
		Intent localIntent = new Intent();
		localIntent.setAction(Intent.ACTION_WEB_SEARCH);
		localIntent.putExtra(SearchManager.QUERY, apk);
		activity.startActivity(localIntent);
	}

	// backup apk
	public static void backupApp(String srcPath, String apkName) {
		String path = SharePreferences.getBackupPath();
		File f = new File(path);
		f.mkdirs();
		FileUtils.CopyFile(srcPath, path + apkName + ".apk", null);
	}

	/**
	 * 从未安装的apk中获取apk的图标 来自 http://blog.csdn.net/sodino/article/details/6215224
	 */
	public static Bitmap getUninstallAPKIcon(String apkPath, String md5) {
		String PATH_PackageParser = "android.content.pm.PackageParser";
		String PATH_AssetManager = "android.content.res.AssetManager";
		try {
			// apk包的文件路径
			// 这是一个Package 解释器, 是隐藏的
			// 构造函数的参数只有一个, apk文件的路径
			// PackageParser packageParser = new PackageParser(apkPath);
			Class pkgParserCls = Class.forName(PATH_PackageParser);
			Class[] typeArgs = new Class[1];
			typeArgs[0] = String.class;
			Constructor pkgParserCt = pkgParserCls.getConstructor(typeArgs);
			Object[] valueArgs = new Object[1];
			valueArgs[0] = apkPath;
			Object pkgParser = pkgParserCt.newInstance(valueArgs);
			// Log.d("ANDROID_LAB", "pkgParser:" + pkgParser.toString());
			// 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况
			DisplayMetrics metrics = new DisplayMetrics();
			metrics.setToDefaults();
			// PackageParser.Package mPkgInfo = packageParser.parsePackage(new
			// File(apkPath), apkPath,
			// metrics, 0);
			typeArgs = new Class[4];
			typeArgs[0] = File.class;
			typeArgs[1] = String.class;
			typeArgs[2] = DisplayMetrics.class;
			typeArgs[3] = Integer.TYPE;
			Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod(
					"parsePackage", typeArgs);
			valueArgs = new Object[4];
			valueArgs[0] = new File(apkPath);
			valueArgs[1] = apkPath;
			valueArgs[2] = metrics;
			valueArgs[3] = 0;
			Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser,
					valueArgs);
			// 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开
			// ApplicationInfo info = mPkgInfo.applicationInfo;
			Field appInfoFld = pkgParserPkg.getClass().getDeclaredField(
					"applicationInfo");
			ApplicationInfo info = (ApplicationInfo) appInfoFld
					.get(pkgParserPkg);
			// uid 输出为"-1"，原因是未安装，系统未分配其Uid。
			// Log.d("ANDROID_LAB", "pkg:" + info.packageName + " uid=" +
			// info.uid);
			// Resources pRes = getResources();
			// AssetManager assmgr = new AssetManager();
			// assmgr.addAssetPath(apkPath);
			// Resources res = new Resources(assmgr, pRes.getDisplayMetrics(),
			// pRes.getConfiguration());
			Class assetMagCls = Class.forName(PATH_AssetManager);
			Constructor assetMagCt = assetMagCls.getConstructor((Class[]) null);
			Object assetMag = assetMagCt.newInstance((Object[]) null);
			typeArgs = new Class[1];
			typeArgs[0] = String.class;
			Method assetMag_addAssetPathMtd = assetMagCls.getDeclaredMethod(
					"addAssetPath", typeArgs);
			valueArgs = new Object[1];
			valueArgs[0] = apkPath;
			assetMag_addAssetPathMtd.invoke(assetMag, valueArgs);
			Resources res = MainApp.sInstance.getResources();
			typeArgs = new Class[3];
			typeArgs[0] = assetMag.getClass();
			typeArgs[1] = res.getDisplayMetrics().getClass();
			typeArgs[2] = res.getConfiguration().getClass();
			Constructor resCt = Resources.class.getConstructor(typeArgs);
			valueArgs = new Object[3];
			valueArgs[0] = assetMag;
			valueArgs[1] = res.getDisplayMetrics();
			valueArgs[2] = res.getConfiguration();
			res = (Resources) resCt.newInstance(valueArgs);
			CharSequence label = null;
			if (info.labelRes != 0) {
				label = res.getText(info.labelRes);
			}
			// Log.d("ANDROID_LAB", "label=" + label);
			// 这里就是读取一个apk程序的图标
			if (info.icon != 0) {
				BitmapDrawable icon = (BitmapDrawable) res
						.getDrawable(info.icon);
				Bitmap bm = icon.getBitmap();
				if (bm != null) {
					FileUtils.Bitmap2JPEG(bm, Define.ICON_CACHE_PATH + md5);
				}
				return bm;
			}
		} catch (Exception e) {
			// e.printStackTrace();
		}
		return null;
	}
}
